#pragma once

#include <linux/types.h>
#include <linux/llist.h>
#include <asm/page.h>

struct page
{
    /* Atomic flags, some possibly updated asynchronously */
    union
    {
        unsigned long flags;
        struct
        {
            unsigned long __flags : 8,
                zone_id : 8;
        };
    };

    /*
     * Five words (20/40 bytes) are available in this union.
     * WARNING: bit 0 of the first word is used for PageTail(). That
     * means the other users of this union MUST NOT use the bit to
     * avoid collision and false-positive PageTail().
     */
    union
    {
        /* Page cache and anonymous pages */
        struct
        {
            struct list_head lru;

            union
            {
                struct list_head buddy_list;

                struct
                {
                    struct llist_node pcp_llist;
                };
            };

            union
            {
                pgoff_t index;       /* Our offset within mapping. */
                unsigned long share; /* share count for fsdax */
            };

            union
            {
                unsigned char order;
                unsigned long private;
            };
        };

        /* slab */
        struct
        {
            void *slab_cache;

            union
            {
                struct list_head slab_list;
            };
            union
            {
                struct
                {
                    void *freelist; /* first free object */
                    union
                    {
                        unsigned long counters;
                        struct
                        {
                            unsigned short inuse;
                            unsigned short objects : 15;
                            /*
                             * If slab debugging is enabled then the
                             * frozen bit can be reused to indicate
                             * that the slab was corrupted
                             */
                            unsigned short frozen : 1;
                        };
                    };
                };
            };
        };
    };

    /*
     * This union is 4 bytes in size.
     */
    union
    {
        /*
         * For head pages of typed folios, the value stored here
         * allows for determining what this page is used for. The
         * tail pages of typed folios will not store a type
         * (page_type == _mapcount == -1).
         *
         * See page-flags.h for a list of page types which are currently
         * stored here.
         *
         * Owners of typed folios may reuse the lower 16 bit of the
         * head page page_type field after setting the page type,
         * but must reset these 16 bit to -1 before clearing the
         * page type.
         */
        unsigned int page_type;

        /*
         * For pages that are part of non-typed folios for which mappings
         * are tracked via the RMAP, encodes the number of times this page
         * is directly referenced by a page table.
         *
         * Note that the mapcount is always initialized to -1, so that
         * transitions both from it and to it can be tracked, using
         * atomic_inc_and_test() and atomic_add_negative(-1).
         */
        atomic_t _mapcount;
    };

    /*
     * Usage count. *DO NOT USE DIRECTLY*. See page_ref.h
     */
    atomic_t _refcount;
};

#include <linux/page-flags.h>
